from configs.response import APIResponse


class BaseSerializer:
    """基础序列化器"""

    class Meta:
        """元类：定义模型、字段以及钩子映射"""

        model = None
        fields = None
        hangers = None
        extra_kwargs = None

    class Hanger:
        """定义钩子函数在Meta中映射"""

        pass

    def __init__(self, data=None):
        self.__data = data
        self.__model = self.get_queryset()
        self.__fields = self.get_fields()
        self.__hangers = self.get_hangers()
        self.__extra_kwargs = self.get_extra_kwargs()

    def get_queryset(self):
        meta = self.Meta()
        if meta.model is None:
            raise APIResponse(code=500, message="model is must!")
        return meta.model

    def get_fields(self):
        meta = self.Meta()
        if meta.fields is None:
            raise APIResponse(code=500, message="fields is must!")
        return meta.fields

    def get_hangers(self):
        meta = self.Meta()
        if meta.hangers is None:
            return dict()
        return meta.hangers

    def get_extra_kwargs(self):
        meta = self.Meta()
        if meta.extra_kwargs is None:
            return dict()
        return meta.extra_kwargs

    def validate(self, params):
        """校验字段"""
        extra_kwargs = self.__extra_kwargs
        if extra_kwargs is None:
            return True
        for item in list(params.keys()):
            # 获取当前字段规则
            rules = extra_kwargs.get(item, dict())
            if rules.get("required"):
                if not params.get(item):
                    raise Exception(f"{item}是必要参数")
            if rules.get("maxlength"):
                if len(params.get(item)) > rules.get("maxlength"):
                    raise Exception(f"{item}超出最大长度限制{rules.get('maxlength')}")

    def get(self, queryset, many=False):
        hanger = self.Hanger()
        if many:
            res_temps = []
            for item in queryset:
                response = dict()
                for field in self.__fields:
                    if self.__extra_kwargs.get(field):
                        if self.__extra_kwargs.get(field).get("write_only") is True:
                            continue
                    tem_value = self.__hangers.get(field)
                    response.setdefault(
                        field,
                        (
                            getattr(hanger, tem_value)(item)
                            if tem_value
                            else getattr(item, field)
                        ),
                    )
                res_temps.append(response)
            return res_temps
        response = dict()
        for field in self.__fields:
            tem_value = self.__hangers.get(field)
            response.setdefault(
                field,
                (
                    getattr(hanger, tem_value)(queryset)
                    if tem_value
                    else getattr(queryset, field)
                ),
            )
        return response

    def create(self):
        data = self.__data
        # 校验字段
        self.validate(data)
        model = self.__model
        model_dict = dict()
        for field in self.__fields:
            if field == "id":
                continue
            if self.__extra_kwargs.get(field):
                if self.__extra_kwargs.get(field).get("read_only") is True:
                    continue
            model_dict.setdefault(field, data.get(field))
        model_obj = model.create(**model_dict)
        return model_obj

    async def update(self, pk):
        data = self.__data
        # 校验字段
        self.validate(data)
        model = await self.__model.get(id=pk)
        for item in list(data.keys()):
            if self.__extra_kwargs.get(item):
                if self.__extra_kwargs.get(item).get("read_only") is True:
                    continue
            setattr(model, item, data.get(item))
        await model.save()
        model_obj = await self.__model.get(id=pk)
        return model_obj

    async def delete(self, pk):
        await self.__model.filter(id=pk).delete()
